// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.core.prefs.connectivity;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.dengues.commons.IDenguesSharedImage;
import org.dengues.commons.connectivity.IConnectivitySettingsConstants;
import org.dengues.commons.utils.ImageUtil;
import org.dengues.core.prefs.connectivity.models.ConnectivityCategory;
import org.dengues.core.prefs.connectivity.models.ConnectivityGenCategory;
import org.dengues.core.prefs.connectivity.models.ConnectivityProperty;
import org.dengues.core.prefs.connectivity.models.ConnectivityProvider;
import org.dengues.core.prefs.connectivity.models.ConnectivityRootCategory;
import org.dengues.core.prefs.connectivity.models.ConnectivitySubCategory;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.viewers.DecorationOverlayIcon;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;

/**
 * qzhang class global comment. Detailled comment <br/>
 * 
 */
public class ConnectivitySettingTreeProvider extends LabelProvider implements ITreeContentProvider, ILabelDecorator {

    private final List<ConnectivityProperty> connectivityInstances = new ArrayList<ConnectivityProperty>();

    // private String modified;

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
     */
    public Object[] getChildren(Object element) {
        if (element instanceof ConnectivityProvider) {
            return ConnectivityProvider.getInstance().getRootCategories().toArray(new ConnectivityCategory[0]);
        } else if (element instanceof ConnectivityRootCategory) {
            return ConnectivityProvider.getInstance().getCategoriesById((ConnectivityCategory) element).toArray(
                    new ConnectivityCategory[0]);
        } else if (element instanceof ConnectivityGenCategory) {
            ConnectivityGenCategory genCategory = (ConnectivityGenCategory) element;
            if (genCategory.getType().getUrl() == null) {
                return ConnectivityProvider.getInstance().getSubCategories(genCategory, genCategory.getType()).toArray(
                        new ConnectivityCategory[0]);
            } else {
                return getDriverDefn(ConnectivityProvider.getInstance().getCategoryId(genCategory));
            }
        } else if (element instanceof ConnectivitySubCategory) {
            return getDriverDefn(ConnectivityProvider.getInstance().getCategoryId((ConnectivitySubCategory) element));
        }
        return new Object[0];
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getDriverDefn".
     * 
     * @param id
     * @return
     */
    private Object[] getDriverDefn(String id) {
        XMLFileManager.setFileName(IConnectivitySettingsConstants.CONNECTIVITY_FILE);
        try {
            // if (connectivityInstances.size() == 0
            // || (modified != null && !(modified.equals(XMLFileManager.getFileDateTimeStamp())))) {
            connectivityInstances.clear();
            for (ConnectivityProperty property : Arrays.asList(XMLFileManager.loadPropertySets())) {
                property.validate();
                connectivityInstances.add(property);
            }
            // modified = XMLFileManager.getFileDateTimeStamp();
            //
            // }
            List<ConnectivityProperty> idprops = new ArrayList<ConnectivityProperty>();
            for (ConnectivityProperty property : connectivityInstances) {
                if (id.equals(ConnectivityProvider.getInstance().getCategoryId(property))) {
                    idprops.add(property);
                }
            }
            return idprops.toArray(new ConnectivityProperty[0]);
        } catch (CoreException ex) {
            ex.printStackTrace();
        }
        return new Object[0];
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
     */
    @Override
    public Image getImage(Object element) {
        if (element instanceof ConnectivityCategory) {
            Image image = ((ConnectivityCategory) element).getImage();
            Image decorateImage = decorateImage(image, element);
            if (decorateImage != null) {
                return decorateImage;
            }
            return image;
        }
        return super.getImage(element);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
     */
    @Override
    public String getText(Object element) {
        if (element instanceof ConnectivityProperty) {
            return ((ConnectivityProperty) element).getName();
        } else if (element instanceof ConnectivityCategory) {
            return ((ConnectivityCategory) element).getId();
        }
        return super.getText(element);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
     */
    public Object getParent(Object element) {
        if (element instanceof ConnectivityCategory) {
            ConnectivityCategory category = (ConnectivityCategory) element;
            if (category.getParent() != null) {
                return category.getParent();
            } else {
                return ConnectivityProvider.getInstance();
            }
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
     */
    public boolean hasChildren(Object element) {
        return getChildren(element).length > 0;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
     */
    public Object[] getElements(Object inputElement) {
        return getChildren(inputElement);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object,
     * java.lang.Object)
     */
    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.viewers.ILabelDecorator#decorateImage(org.eclipse.swt.graphics.Image, java.lang.Object)
     */
    public Image decorateImage(Image image, Object element) {
        if (element instanceof ConnectivityProperty) {
            ConnectivityProperty property = (ConnectivityProperty) element;
            if (!property.isValid()) {
                DecorationOverlayIcon icon = new DecorationOverlayIcon(image, ImageUtil
                        .getDescriptor(IDenguesSharedImage.PREFS_ERROR_ICON), IDecoration.TOP_LEFT);
                return icon.createImage();
            } else {
                DecorationOverlayIcon icon = new DecorationOverlayIcon(image, ImageUtil
                        .getDescriptor(IDenguesSharedImage.PREFS_OK_ICON), IDecoration.TOP_LEFT);
                return icon.createImage();
            }
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.viewers.ILabelDecorator#decorateText(java.lang.String, java.lang.Object)
     */
    public String decorateText(String text, Object element) {
        return text;
    }

    /**
     * qzhang Comment method "getConnectivityInstances".
     * 
     * @return
     */
    public List<ConnectivityProperty> getConnectivityInstances() {
        return this.connectivityInstances;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getExistPropertyNames".
     * 
     * @param descriptor
     * @return
     */
    public List<String> getExistPropertyNames(ConnectivityCategory descriptor) {
        List<String> list = new ArrayList<String>();
        Object[] children = getChildren(descriptor);
        for (Object object : children) {
            if (object instanceof ConnectivityProperty) {
                ConnectivityProperty property = (ConnectivityProperty) object;
                list.add(property.getName());
            }
        }
        return list;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "removeConnectivityInstance".
     * 
     * @param id
     * @param name
     */
    private ConnectivityProperty getConnectivityInstance(String id, String name) {
        for (ConnectivityProperty property : getConnectivityInstances()) {
            if (property.getId().equals(id) && name.equals(property.getName())) {
                return property;
            }
        }
        return null;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "addConnectivityInstance".
     * 
     * @param instance
     */
    public synchronized void addConnectivityInstance(ConnectivityProperty instance) {
        getConnectivityInstances().add(instance);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "removeConnectivityInstance".
     * 
     * @param instance
     */
    public synchronized void removeConnectivityInstance(ConnectivityProperty instance) {
        getConnectivityInstances().remove(instance);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "modifyConnectivityInstance".
     * 
     * @param instance
     * @param name
     */
    public synchronized void modifyConnectivityInstance(ConnectivityProperty instance, String name) {
        ConnectivityProperty orgInstance = getConnectivityInstance(instance.getId(), name);
        if (orgInstance != null) {
            orgInstance.setName(instance.getName());
            orgInstance.setDriverClasses(instance.getDriverClasses());
            orgInstance.setBaseProperties(instance.getBaseProperties());
            orgInstance.setParent(instance.getParent());
            orgInstance.setType(instance.getType());
        } else {
            throw new RuntimeException("name isn't exsit. " + name);
        }
    }
}
